﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    public class HolyPaladinCombatClass : KingWoWAbstractBaseClass
    {

        private static string Name = "KingWoW HolyPaladin";

        
        #region CONSTANT AND VARIABLES

        //START OF CONSTANTS ==============================
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        private const string DRINK = "Drink";
        private const string FOOD = "Food";

        //SEAL
        private const string SEAL_OF_INSIGHT = "Seal of Insight";
        private const string SEAL_OF_TRUTH = "Seal of Truth";
        private const string SEAL_OF_RIGHTEOUSNESS = "Seal of Righteousness";

        //BLESSING
        private const string BLESSING_OF_KINGS = "Blessing of Kings";
        private const string BLESSING_OF_MIGHT = "Blessing of Might";
        
        //HAND
        private const string HAND_OF_FREEDOM = "Hand of Freedom";
        private const string HAND_OF_PROTECTION = "Hand of Protection";
        private const string HAND_OF_SACRIFICE = "Hand of Sacrifice";
        private const string HAND_OF_SALVATION = "Hand of Salvation";
                   
        
        private const string CRUSADER_STRIKE = "Crusader Strike";
        private const string JUDGEMENT = "Judgment";
        private const string HOLY_WRATH = "Holy Wrath";
        private const string WORD_OF_GLORY = "Word of Glory";
        private const string GUARDIAN_OF_ANCIENT_KING = "Guardian of Ancient Kings";
        private const string DIVINE_PROTECTION = "Divine Protection";
        private const string AVENGING_WRATH = "Avenging Wrath";
        private const string REBUKE = "Rebuke";
        private const string FIST_OF_JUSTICE = "Fist of Justice";     
        private const string HAMMER_OF_JUSTICE = "Hammer of Justice";
        private const string CLEANSE = "Cleanse";      
        private const string FLASH_OF_LIGHT = "Flash of Light";
        private const string LAY_ON_HANDS = "Lay on Hands";
        private const string DIVINE_SHIELD = "Divine Shield";
        private const string RESURRECTION = "Redemption";
        private const string HAND_OF_PURITY = "Hand Of Purity";
        private const string BEACON_OF_LIGHT = "Beacon of Light";
        private const string BEACON_OF_FAITH = "Beacon of Faith";
        private const string HOLY_SHOCK = "Holy Shock";
        


        //TALENT
        private const string ETERNAL_FLAME = "Eternal Flame";  //same use of Word of Glory
        private const string SACRED_SHIELD = "Sacred Shield"; 
        private const string SELFLESS_HEALER = "Selfless Healer"; //Flash of Light on 3 stack

        private const string HOLY_AVENGER = "Holy Avenger";
        private const string SANCTIFIED_WRATH = "Sanctified Wrath";
        private const string DIVINE_PURPOSE = "Divine Purpose";

        private const string EXECUTION_SENTENCE = "Execution Sentence";
        private const string HOLY_PRISM= "Holy Prism";
        private const string LIGHTS_HAMMER = "Light's Hammer";

        private const string FORBEARANCE = "Forbearance";

        //END OF SPELLS AND AURAS ==============================
        private KingWoWUtility utils = null;
        private ExtraUtils extra = null;
        private Movement movement = null;
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private TalentManager talents = new TalentManager();

        private WoWUnit tank = null;
        private WoWUnit off_tank = null;
        private WoWUnit lastTank = null;
        private WoWUnit lastOffTank = null;
        private const string TANK_CHANGE = "TANK CHANGED";
        private const string OFF_TANK_CHANGE = "OFFTANK CHANGED";
        
        WoWUnit CurrentHealtarget = null;
        WoWUnit healTarget = null;
        WoWUnit AttackTarget = null;
        //END OF CONSTANTS ==============================

        #endregion

        #region Hotkeys
        private static bool IsCRPaused = false;

        private static DateTime nextTime_Pause_Resume_Allowed;

        public static void SetnextTime_Pause_Resume_Allowed()
        {
            //1 seconds avoid duuble cast
            nextTime_Pause_Resume_Allowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private static void InitializeHotkey()
        {
            HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            RegisterHotkeyAssignment("Routine Pause", (Keys)HolyPaladinSettings.Instance.PauseKey, hk =>
            {
                try
                {
                    if (nextTime_Pause_Resume_Allowed < DateTime.Now)
                    {
                        if (!IsCRPaused)
                        {
                            IsCRPaused = true;
                            Lua.DoString(@"print('\124cFFE61515 Paused!')");
                            Logging.Write("KingWoW Routine Paused!");
                        }
                        else
                        {
                            IsCRPaused = false;
                            Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                            Logging.Write("KingWoW Routine Resumed!");
                        }
                        SetnextTime_Pause_Resume_Allowed();
                    }
                }
                catch (Exception e)
                {
                    Logging.Write(e.StackTrace);
                }
            });

        }

        private static void RemoveHotkeys()
        {
            HotkeysManager.Unregister("Routine Pause");
        }

        private static void ReRegisterHotkeys()
        {
            RemoveHotkeys();
            RegisterHotkeys();
        }
        #endregion

        public HolyPaladinCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            SoloBotType = false;
            BaseBot = "unknown";
        }

        public override bool Combat
        {
            get
            {
                extra.UseRacials();
                extra.UseTrinket1();
                extra.UseTrinket2();
                extra.UseHealPotion_Healthstone();
                extra.UseManaItem();
                CombatRotation();
                return false;
            }          
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.SafeName);
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");
                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                InitializeHotkey();
                RegisterHotkeys();
                return true; ;
            }
        }

        void BotEvents_OnBotStart(EventArgs args)
        {
            talents.Update();
            BotUpdate();
            ReRegisterHotkeys();
        }

        public override bool UpdateTalentAndGlyph
        {
            get
            {
                talents.Update();
                BotUpdate();
                return true;

            }
        }

        public override bool NeedCombatBuffs { get { return Buff(); } }

        public override bool NeedPreCombatBuffs { get { return Buff(); } }

        public override bool NeedPullBuffs { get { return Buff(); } }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead) return false;
                if ((utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD)) && (Me.ManaPercent < 100 || Me.HealthPercent < 100))
                    return true;
                if (Me.ManaPercent <= HolyPaladinSettings.Instance.ManaPercent &&
                !utils.isAuraActive(DRINK) && !Me.Combat && !Me.IsMoving && !Me.IsCasting)
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking/Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                }
                if (Me.HealthPercent <= HolyPaladinSettings.Instance.HealthPercent &&
                !utils.isAuraActive(FOOD) && !Me.Combat && !Me.IsMoving && !Me.IsCasting)
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return false;
                    }
                }
                return false;
            }
        }

        private bool PlaceBeacons()
        {

            return false;
        }

        private bool HolyShock()
        {
            if (utils.CanCast(HOLY_SHOCK))
            {
                WoWUnit holyShockTarget = null;
                if (healTarget != null && healTarget.HealthPercent < 100)
                    holyShockTarget = healTarget;
                else if (tank != null && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40 && tank.InLineOfSpellSight)
                    holyShockTarget = tank;
                else
                    holyShockTarget = Me;
                if (holyShockTarget != null)
                {
                    utils.LogActivity(HOLY_SHOCK, holyShockTarget.SafeName);
                    return utils.Cast(HOLY_SHOCK, holyShockTarget);
                }
            }
            return false;

        }

        public override bool Pulse
        {
            get
            {
                if (Me.IsDead) return MyDeath();
                if (Me.Combat || (Me.Mounted && !HolyPaladinSettings.Instance.AutoDismountOnCombat) || IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced || utils.IsGlobalCooldown() || utils.MeIsChanneling || Me.IsCasting
                || utils.isAuraActive(DRINK) || utils.isAuraActive(FOOD))
                    return false;

                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }
                //full party or me
                if (!Me.Combat && !IsCRPaused && !Me.Mounted && HolyPaladinSettings.Instance.OOCHealing)
                {
                    Resurrect();

                    healTarget = utils.GetHealTarget(40f, HolyPaladinSettings.Instance.HealNPC);
                    if (healTarget != null)
                    {
                        PlaceBeacons();
                        HolyShock();
                    }
                }
                if (!IsCRPaused && !Me.Combat && ((tank != null && tank.Combat) || (off_tank != null && off_tank.Combat)))
                    return CombatRotation();
                return false;
            }
        }

        private DateTime nextTimeTryReviveAllowed=DateTime.Now;

        public void SetNextTimeTryRevive()
        {
            //3 seconds avoid duuble cast
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        public override bool Pull
        {
            get
            {
                WoWUnit target = Me.CurrentTarget;
                if (target != null && target.IsDead)
                    Me.ClearTarget();
                else if (target != null && !target.IsDead)
                {
                    if (SoloBotType)
                    {
                        if(!Me.IsMoving)
                            Me.SetFacing(target);
                        if (target.InLineOfSpellSight || target.Distance > HolyPaladinSettings.Instance.PullDistance)
                        {
                            movement.KingHealMove(target, HolyPaladinSettings.Instance.PullDistance);
                        }
                    }
                    
                    //TODO
                }
                return false;
            }
        }

        private bool Buff()
        {
            if (utils.Mounted())
                return false;
            if (!utils.isAuraActive(SEAL_OF_INSIGHT))
            {
                utils.LogActivity(SEAL_OF_INSIGHT);
                return utils.Cast(SEAL_OF_INSIGHT);
            }
            if (HolyPaladinSettings.Instance.BlessingToUse == HolyPaladinSettings.BlessingType.KING)
            {
                //KING
                if (!utils.isAuraActive(BLESSING_OF_KINGS, Me) &&
                    !utils.isAuraActive("Mark of the Wild", Me) &&
                    !utils.isAuraActive("Embrace of the Shale Spider", Me) &&
                    !utils.isAuraActive("Legacy of the Emperor", Me) &&
                    utils.CanCast(BLESSING_OF_KINGS))
                {
                    utils.LogActivity(BLESSING_OF_KINGS);
                    return utils.Cast(BLESSING_OF_KINGS);
                }
            }

            if (HolyPaladinSettings.Instance.BlessingToUse == HolyPaladinSettings.BlessingType.MIGTH)
            {
                //MIGTH
                if (!utils.isAuraActive(BLESSING_OF_MIGHT, Me) &&
                    !utils.isAuraActive("Roar of Courage", Me) &&
                    !utils.isAuraActive("Grace of Air", Me) &&
                    !utils.isAuraActive("Spirit Beast Blessing", Me) &&
                    utils.CanCast(BLESSING_OF_MIGHT))
                {
                    utils.LogActivity(BLESSING_OF_MIGHT);
                    return utils.Cast(BLESSING_OF_MIGHT);
                }
            }
            return false;
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;
        }

        private bool CombatRotation()
        {
            
            //TODO
            return false;
           
        }

        private bool Resurrect()
        {
            foreach (WoWPlayer player in utils.GetResurrectTargets(40f))
            {
                if (Blacklist.Contains(player.Guid, BlacklistFlags.All)) continue;
                else
                {
                    if (player.Distance > 40 || !player.InLineOfSpellSight) return false;
                    else if (utils.CanCast(RESURRECTION, player) && HolyPaladinSettings.Instance.UseRedemption && !Me.IsMoving)
                    {
                        utils.LogActivity(RESURRECTION, player.SafeName);
                        Blacklist.Add(player, BlacklistFlags.All,new TimeSpan(0, 0, 60));
                        return utils.Cast(RESURRECTION, player);
                    }

                    return false;
                }
            }

            return false;
        }
    }
}
